package thread.ch04;

import java.util.concurrent.atomic.AtomicInteger;

import thread.annotation.NotThreadSafe;

/**
 * NumberRange
 * <p/>
 * Number range class that does not sufficiently protect its invariants
 * 
 * 一个类的不变约束也可以约束多个状态对象<br />
 * 这种多变量的不变约束需要原子性：必须在单一的原子操作中获取或更新相互关联的变量。<br/>
 * 你不能先更新一个变量，然后释放锁，在重获锁，在更新其他变量。因为当释放了锁后，可能会使对象处于无效状态。<br />
 * 当不变约束涉及多个变量时，任何一个操作在访问相关变量期间，线程必须占有保护这些变量的锁.
 * <p />
 * 虽然底层的AtomicInteger是线程安全的，但是组合的类却不是。因为状态变量lower和upper不是彼此独立的，
 * NumberRange不能简单地将线程安全性委托给线程安全的状态变量上。
 * 
 * @author Edgar Zhang
 * 
 */
@NotThreadSafe
public class NumberRange {

	private final AtomicInteger lower = new AtomicInteger(0);
	private final AtomicInteger upper = new AtomicInteger(0);

	public void setLower(int i) {
		// Warning -- unsafe check-then-act
		if (i > upper.get()) {
			throw new IllegalArgumentException("can't set lower to " + i
					+ " > upper");
		}
		lower.set(i);
	}

	public void setUpper(int i) {
		// Warning -- unsafe check-then-act
		if (i < lower.get()) {
			throw new IllegalArgumentException("can't set upper to " + i
					+ " < lower");
		}
		lower.set(i);
	}

	public boolean isInRange(int i) {
		return (i >= lower.get() && i <= upper.get());
	}
}
